﻿using Abp.Application.Services;
using Abp.Domain.Repositories;
using MyCompanyName.AbpZeroTemplate.Prm.Project.Dto;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.AutoMapper;
using Abp.Runtime.Session;
using MyCompanyName.AbpZeroTemplate.Prm.Admin;

namespace MyCompanyName.AbpZeroTemplate.Prm.Project
{
    public class SummaryAppService : AbpZeroTemplateAppServiceBase, ISummaryAppService
    {
        private readonly IRepository<ProjectSummary, int> projectSummaryRepository;
        private readonly IRepository<Laboratory, int> laboratoryRepository;
        private readonly ProjectManager projectManagerRepository;

        public SummaryAppService(
            IRepository<ProjectSummary, int> _projectSummaryRepository,
            IRepository<Laboratory, int> _laboratoryRepository,
            ProjectManager _projectManagerRepository)
        {
            projectSummaryRepository = _projectSummaryRepository;
            laboratoryRepository = _laboratoryRepository;
            projectManagerRepository = _projectManagerRepository;
        }


        /// <summary>
        /// 项目概要信息
        /// </summary>
        /// <returns></returns>
        public GetSummaryOutPut Get(string StartTime, int LaboratoryId = 0)
        {

            var userId = AbpSession.GetUserId();
            var lab = new Laboratory();
            if (LaboratoryId > 0)
            {
                lab = laboratoryRepository.Get(LaboratoryId);
            }
            else
            {
                lab = laboratoryRepository.GetAll().Where(x => x.PrincipalId == userId).SingleOrDefault();
            }
            if (lab == null)
            {
                throw new Abp.UI.UserFriendlyException("系统提示", "当前用户不是实验室负责人");
            }
            var opt = new GetSummaryOutPut();

            var dt = DateTime.Now;
            if (!string.IsNullOrEmpty(StartTime))
            {
                dt = DateTime.Parse(StartTime);
            }
            var mondayDate = DateHelper.GetMondayDate(dt);
            var summary = projectSummaryRepository.GetAll().Where(x => x.FirstTime == mondayDate.Date && x.LaboratoryId == LaboratoryId).SingleOrDefault();
            if (summary == null)
            {
                var sunDayDate = DateHelper.GetSundayDate(dt);
                var week = DateHelper.GetWeek(dt);
                summary = new ProjectSummary();
                summary.StartTime = mondayDate;
                summary.EndTime = sunDayDate;
                summary.Year = DateTime.Now.Year;
                summary.Week = week;
            }

            var labUsers = UserManager.Users.Where(x => x.LaboratoryId == lab.Id).ToList();
            opt = summary.MapTo<GetSummaryOutPut>();
            opt.Laboratory = lab.Name;
            opt.LaboratoryId = lab.Id;
            opt.RdCenter = lab.RdCenter.Name;
            opt.LabUserNum = labUsers.Count();
            opt.LabUserNames = string.Join(",", labUsers.Select(q => q.UserName));

            List<ProjectSummaryInfo> results = new List<ProjectSummaryInfo>();
            if (!string.IsNullOrEmpty(summary.ToDoProject))
            {
                results = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProjectSummaryInfo>>(summary.ToDoProject);
            }

            var users = labUsers.Select(x => x.Id);
            var projects = projectManagerRepository.projectTeamRepository.GetAll().Where(x => users.Any(m => m == x.UserId)).Select(x => x.ProjectId);

            var todos = new List<ProjectInfo>();
            if (projects.Any())
            {
                todos = projectManagerRepository.projectRepository.GetAll().Where(x => projects.Any(m => m == x.Id) && x.ActualStartDate < opt.EndTime || x.ActualEndDate > opt.StartTime).ToList();
            }
            foreach (var m in todos)
            {
                if (!results.Any(x => x.ProjectNo == m.ProjectNo))
                {
                    var userIds = projectManagerRepository.projectTeamRepository.GetAll().Where(q => q.ProjectId == m.Id).Select(x => x.UserId);
                    var teams = string.Join(",", UserManager.Users.Where(x => userIds.Any(t => t == x.Id)).Select(x => x.UserName));
                    results.Add(new ProjectSummaryInfo()
                    {
                        ActualDate = m.PlanEndDate,
                        PlanDate = m.PlanEndDate,
                        ProjectNo = m.ProjectNo,
                        ProjectName = m.ProjectName,
                        Remark = m.TaskNote,
                        StartDate = m.ActualStartDate,
                        TargetDate = m.TargetEndDate,
                        Team = teams
                    });
                }
            }
            opt.ToDos = results;

            if (!string.IsNullOrEmpty(summary.NextProject))
            {
                opt.Nexts = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProjectSummaryInfo>>(summary.NextProject);
            }
            return opt;
        }



        public GetSummaryOutPut GetToEdit()
        {

            var userId = AbpSession.GetUserId();
            var lab = laboratoryRepository.GetAll().Where(x => x.PrincipalId == userId).SingleOrDefault();

            if (lab == null)
            {
                throw new Abp.UI.UserFriendlyException("系统提示", "当前用户不是实验室负责人");
            }
            var opt = new GetSummaryOutPut();

            var dt = DateTime.Now;
            var mondayDate = DateHelper.GetMondayDate(dt);
            var summary = projectSummaryRepository.GetAll().Where(x => x.FirstTime == mondayDate.Date && x.LaboratoryId == lab.Id).SingleOrDefault();
            if (summary == null)
            {
                var sunDayDate = DateHelper.GetSundayDate(dt);
                var week = DateHelper.GetWeek(dt);
                summary = new ProjectSummary();
                summary.StartTime = mondayDate;
                summary.EndTime = sunDayDate;
                summary.Year = DateTime.Now.Year;
                summary.Week = week;
            }

            var labUsers = UserManager.Users.Where(x => x.LaboratoryId == lab.Id).ToList();
            opt = summary.MapTo<GetSummaryOutPut>();
            opt.Laboratory = lab.Name;
            opt.LaboratoryId = lab.Id;
            opt.RdCenter = lab.RdCenter.Name;
            opt.LabUserNum = labUsers.Count();
            opt.LabUserNames = string.Join(",", labUsers.Select(q => q.UserName));

            List<ProjectSummaryInfo> results = new List<ProjectSummaryInfo>();
            var users = labUsers.Select(x => x.Id);
            //todo:可能需要调整，目前有项目成员参与的项目，室主任都要写概要；
            var projects = projectManagerRepository.projectTeamRepository.GetAll().Where(x => !x.IsDeleted && users.Any(m => m == x.UserId)).Select(x => x.ProjectId);

            var todos = new List<ProjectInfo>();
            if (projects.Any())
            {
                todos = projectManagerRepository.projectRepository.GetAll().Where(x => projects.Any(m => m == x.Id) && x.ActualStartDate < opt.EndTime || x.ActualEndDate > opt.StartTime).ToList();
            }
            foreach (var m in todos)
            {

                var userIds = projectManagerRepository.projectTeamRepository.GetAll().Where(q => q.ProjectId == m.Id).Select(x => x.UserId);
                var teams = string.Join(",", UserManager.Users.Where(x => userIds.Any(t => t == x.Id)).Select(x => x.UserName));
                results.Add(new ProjectSummaryInfo()
                {
                    ActualDate = m.PlanEndDate,
                    PlanDate = m.PlanEndDate,
                    ProjectNo = m.ProjectNo,
                    ProjectName = m.ProjectName,
                    Remark = m.TaskNote,
                    StartDate = m.ActualStartDate,
                    TargetDate = m.TargetEndDate,
                    Team = teams
                });

            }
            opt.ToDos = results;

            if (!string.IsNullOrEmpty(summary.NextProject))
            {
                opt.Nexts = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProjectSummaryInfo>>(summary.NextProject);
            }
            return opt;
        }





        public async Task CreateOrEdit(CreateOrEditSummaryInPut input)
        {
            var summary = projectSummaryRepository.GetAll()
                .Where(x =>
                    x.Week == input.Week
                    && x.Year == input.Year
                    && x.LaboratoryId == input.LaboratoryId)
                .SingleOrDefault();

            if (summary == null)
            {
                var model = input.MapTo<ProjectSummary>();
                model.FirstTime = model.StartTime.Date;
                var userId = AbpSession.GetUserId();
                model.Principal = UserManager.Users.Where(x => x.Id == userId).SingleOrDefault().UserName;
                model.CreatorUserId = userId;
                await projectSummaryRepository.InsertAsync(model);
            }
            else
            {
                summary.LabUserNum = input.LabUserNum;
                summary.LabUserNames = input.LabUserNames;
                summary.LaboratoryId = input.LaboratoryId;
                summary.Status = input.Status;
                summary.NowStaffNeed = input.NowStaffNeed;
                summary.TwoWeekNeed = input.TwoWeekNeed;
                summary.FourWeekNeed = input.FourWeekNeed;
                summary.SixWeekNeed = input.SixWeekNeed;
                summary.EightWeekNeed = input.EightWeekNeed;
                summary.NowIdleNum = input.NowIdleNum;
                summary.TwoWeekIdleNum = input.TwoWeekIdleNum;
                summary.FourWeekIdleNum = input.FourWeekIdleNum;
                summary.SixWeekIdleNum = input.SixWeekIdleNum;
                summary.EightWeekIdleNum = input.EightWeekIdleNum;
                summary.ToDoProject = input.ToDoProject;
                summary.NextProject = input.NextProject;
                summary.Note = input.Note;
            }

            if (!string.IsNullOrEmpty(input.ToDoProject))
            {
                var todoProjects = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProjectSummaryInfo>>(input.ToDoProject);
                foreach (var item in todoProjects)
                {
                    var p = projectManagerRepository.projectRepository.GetAll().Where(x => x.ProjectNo.Equals(item.ProjectNo)).FirstOrDefault();
                    if (p != null)
                    {
                        p.TaskNote = item.Remark;
                    }
                }

            }

        }


        public List<GetSummaryOutPut> GetStatistics(DateTime StartTime)
        {
            List<GetSummaryOutPut> results = new List<GetSummaryOutPut>();
            var list = projectSummaryRepository.GetAll().Where(x => x.FirstTime <= StartTime && x.EndTime >= StartTime).ToList();
            foreach (var item in list)
            {
                var lab = laboratoryRepository.Get(item.LaboratoryId);
                results.Add(new GetSummaryOutPut()
                {
                    RdCenter = lab.RdCenter.Name,
                    Principal = item.Principal,
                    LabUserNum = item.LabUserNum,
                    Laboratory = lab.Name,
                    LabUserNames = item.LabUserNames,
                    NowStaffNeed = item.NowStaffNeed,
                    TwoWeekNeed = item.TwoWeekNeed,
                    FourWeekNeed = item.FourWeekNeed,
                    SixWeekNeed = item.SixWeekNeed,
                    EightWeekNeed = item.EightWeekNeed,
                    NowIdleNum = item.NowIdleNum,
                    TwoWeekIdleNum = item.TwoWeekIdleNum,
                    FourWeekIdleNum = item.FourWeekIdleNum,
                    SixWeekIdleNum = item.SixWeekIdleNum,
                    EightWeekIdleNum = item.EightWeekIdleNum
                });
            }
            return results;
        }


        public GetYearAndWeekOutPut GetYearAndWeek(GetYearAndWeekInPut input)
        {
            var outPut = new GetYearAndWeekOutPut();
            DateTime dt = input.WeekTime;

            switch (input.WeekType)
            {
                case WeekType.Now:
                    break;
                case WeekType.上一周:
                    dt = dt.AddDays(-1);
                    break;
                case WeekType.下一周:
                    dt = dt.AddDays(7);
                    break;
                default:
                    break;
            }
            var monDay = DateHelper.GetMondayDate(dt);
            var sunDay = DateHelper.GetSundayDate(dt);
            outPut.StartTime = monDay.ToString("yyyy-MM-dd");
            outPut.EndTime = sunDay.ToString("yyyy-MM-dd");
            outPut.Year = monDay.Year;
            outPut.Week = DateHelper.GetWeek(dt);
            return outPut;
        }


        public List<GetSummaryOutPut> GetHistory()
        {
            var userId = AbpSession.GetUserId();
            var lab = laboratoryRepository.GetAll().Where(x => x.PrincipalId == userId).SingleOrDefault();
            if (lab == null)
            {
                throw new Abp.UI.UserFriendlyException("系统提示", "当前用户不是实验室负责人");
            }
            var alls = projectSummaryRepository.GetAll().OrderByDescending(x => x.Year).ThenBy(x => x.Week).Where(x => x.LaboratoryId == lab.Id).ToList();
            List<GetSummaryOutPut> results = new List<GetSummaryOutPut>();
            foreach (var item in alls)
            {
                var model = item.MapTo<GetSummaryOutPut>();
                model.Laboratory = lab.Name;
                model.RdCenter = lab.RdCenter.Name;
                if (!string.IsNullOrEmpty(item.ToDoProject))
                {
                    model.ToDos = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProjectSummaryInfo>>(item.ToDoProject);
                }
                if (!string.IsNullOrEmpty(item.NextProject))
                {
                    model.Nexts = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProjectSummaryInfo>>(item.NextProject);
                }
                results.Add(model);
            }
            return results;
        }


        public GetProjectWeekly GetProjectWeekly(string StartTime, int LaboratoryId = 0)
        {
            var lab = laboratoryRepository.Get(LaboratoryId);
            var outPut = new GetProjectWeekly() { Laboratory = lab.Name, IsSubmit = false, Projects = new List<_ProjectInfo>() };

            var dt = DateTime.Parse(StartTime);
            var summary = projectSummaryRepository.GetAll().Where(x => x.LaboratoryId == LaboratoryId && x.FirstTime == dt).SingleOrDefault();

            if (summary != null)
            {
                outPut.IsSubmit = true;
                var todos = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProjectSummaryInfo>>(summary.ToDoProject);
                foreach (var item in todos)
                {
                    var project = projectManagerRepository.projectRepository.GetAll().Where(x => x.ProjectNo == item.ProjectNo).SingleOrDefault();
                    var weekProject = new _ProjectInfo() { Name = project.ProjectName, ProjectNo = project.ProjectNo, Attachments = new List<_Attachment>() };
                    outPut.Projects.Add(weekProject);
                    //项目周报
                    var weekFiles = projectManagerRepository.projectDocmeutRepository.GetAll().Where(x => x.ProjectId == project.Id && x.DocTypeId == ProjectConst.周报).ToList();
                    foreach (var f in weekFiles)
                    {
                        var attach = new _Attachment() { Name = f.Name, Path = f.FullUrl, Size = f.Length };
                        weekProject.Attachments.Add(attach);
                    }
                }
            }
            return outPut;
        }

        public WeekSummaryDataDto GetWeekSummaryData(DateTime mondayDate)
        {

            List<Status> otherDoingProject = new List<Status>();
            otherDoingProject.Add(Status.完成);
            otherDoingProject.Add(Status.暂停);
            otherDoingProject.Add(Status.终止);

            var finishProjectIds = projectManagerRepository.projectProgressRepository.GetAll()
                .Where(x => otherDoingProject.Contains(x.Status) && x.ReportTime >= mondayDate)
                .Select(x => x.ProjectId).Distinct().ToList();

            var doingProjects = projectManagerRepository.projectRepository.GetAll()
                .Where(x => x.Status == Status.进行中 || finishProjectIds.Contains(x.Id))
                .OrderBy(x => x.PlanEndDate)
                .ToList();

            var projectProgress = projectManagerRepository.projectProgressRepository.GetAll().ToList();



            return null;
        }

        /// <summary>
        /// XX时间段内的进行中的项目
        /// </summary>
        /// <param name="mondayDate"></param>
        /// <returns></returns>
        public List<ProjectInfo> GetWeekSummaryProjects(DateTime mondayDate)
        {

            List<Status> otherDoingProject = new List<Status>();
            otherDoingProject.Add(Status.完成);
            otherDoingProject.Add(Status.暂停);
            otherDoingProject.Add(Status.终止);

            var finishProjectIds = projectManagerRepository.projectProgressRepository.GetAll()
                .Where(x => otherDoingProject.Contains(x.Status) && x.ReportTime >= mondayDate)
                .Select(x => x.ProjectId).Distinct().ToList();

            var doingProjects = projectManagerRepository.projectRepository.GetAll()
                .Where(x => x.Status == Status.进行中 || finishProjectIds.Contains(x.Id))
                .OrderBy(x => x.PlanEndDate)
                .ToList();

            return doingProjects;
        }

    }
}
